/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { ts, native, HomeCheckHint } from 'qvog-dsl';

const SEVERITY = 1;
const DOC_PATH = 'docs/no-dupe-class-members.md';
const DESCRIPTION = 'Disallow duplicate class members.';

interface MemberInfo {
  name: string;
  signature: string;
  isStatic: boolean;
  kind: string;
  node: ts.Node;
}

export default native<HomeCheckHint>()()
  .match(ts.isClassDeclaration)
  .when((node) => {
    if (!node.members) { return false };

    const memberMap = new Map<string, MemberInfo[]>();

    for (const member of node.members) {
      // 获取成员名
      let memberName = getMemberName(member);
      if (!memberName) { continue };

      // 获取成员类型和签名
      let memberKind = getMemberKind(member);
      let memberSignature = getMemberSignature(member);
      let isStatic = hasStaticModifier(member);

      if (!memberMap.has(memberName)) {
        memberMap.set(memberName, []);
      }
      memberMap.get(memberName)!.push({ name: memberName, signature: memberSignature, isStatic, kind: memberKind, node: member });
    }

    // 检测重复
    for (const [, members] of memberMap) {
      if (members.length <= 1) { continue };
      for (let i = 0; i < members.length; i++) {
        for (let j = i + 1; j < members.length; j++) {
          if (
            members[i].kind === members[j].kind &&
            members[i].signature === members[j].signature &&
            members[i].isStatic === members[j].isStatic
          ) {
            return true;
          }
        }
      }
    }

    return false;
  })
  .report({
    severity: SEVERITY,
    description: DESCRIPTION,
    docPath: DOC_PATH,
  });

//获取成员名
function getMemberName(member: ts.ClassElement): string | null {
  if (!member.name) { return null };
  if (ts.isIdentifier(member.name)) { return member.name.text };
  if (ts.isStringLiteral(member.name) || ts.isNumericLiteral(member.name)) { 
    return member.name.text;
  };
  return null;
}

//获取成员类型
function getMemberKind(member: ts.ClassElement): string {
  if (ts.isMethodDeclaration(member)) { return 'method' };
  if (ts.isPropertyDeclaration(member)) { return 'property' };
  if (ts.isGetAccessorDeclaration(member)) { return 'getter' };
  if (ts.isSetAccessorDeclaration(member)) { return 'setter' };
  return 'unknown';
}

//获取成员签名
function getMemberSignature(member: ts.ClassElement): string {
  if (ts.isMethodDeclaration(member) || ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)) {
    const params = member.parameters.map(p => p.getText()).join(',');
    const returnType = (member as ts.MethodDeclaration).type?.getText() ?? 'void';
    return `(${params}):${returnType}`;
  }
  return '';
}

//判断是否有 static 修饰符
function hasStaticModifier(member: ts.ClassElement): boolean {
  return member.modifiers?.some(mod => mod.kind === ts.SyntaxKind.StaticKeyword) ?? false;
}
